package com.zkyc.framework.website.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.zkyc.framework.common.constant.Constant;
import com.zkyc.framework.common.constant.NumberConstant;
import com.zkyc.framework.common.exception.ResultCode;
import com.zkyc.framework.common.mapper.CenterMapper;
import com.zkyc.framework.common.mapper.OrganizationMapper;
import com.zkyc.framework.common.mapper.UserMapper;
import com.zkyc.framework.common.pojo.*;
import com.zkyc.framework.common.utils.CopyBeanUtils;
import com.zkyc.framework.common.utils.WebsiteUtil;
import com.zkyc.framework.common.vo.ResultVO;
import com.zkyc.framework.common.vo.website.*;
import com.zkyc.framework.website.config.JedisPoolFactory;
import com.zkyc.framework.website.mapper.ColumnMapper;
import com.zkyc.framework.website.mapper.MoudleMapper;
import com.zkyc.framework.website.mapper.TagMapper;
import com.zkyc.framework.website.service.ColumnService;
import com.zkyc.framework.website.service.ContentService;
import com.zkyc.framework.website.service.MoudleService;
import com.zkyc.framework.website.util.TokenUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

import static com.zkyc.framework.common.constant.Constant.REDIS_PREFIX;
import static com.zkyc.framework.common.constant.NumberConstant.*;

/**
 * (Moudle)表服务实现类
 *
 * @author libingchuan
 * @since 2022-05-24 16:33:29
 */
@Slf4j
@Service("moudleService")
public class MoudleServiceImpl implements MoudleService {
    @Resource
    private MoudleMapper moudleMapper;
    @Resource
    private ColumnMapper columnMapper;
    @Resource
    private TagMapper tagMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private CenterMapper centerMapper;

    @Resource
    private OrganizationMapper organizationMapper;

    private static String MOUDLEKEY = "moudle_";

    private static String MOUDLEDATAKEY = "moudle_data_";

    @Resource
    private ColumnService columnService;

    @Resource
    private ContentService contentService;

    AtomicBoolean isShow = new AtomicBoolean(false);


    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Moudle queryById(Integer id) {
        Moudle moudle = moudleMapper.selectById(id);
        //List<Column> columns = getColumns(id);
        JSONArray columns = getColumns(id);
        if (columns.size() > 0) {
            moudle.setColumnList(columns);
        }
        //setChildrenList(moudle);
        return moudle;
    }

    private JSONArray getColumns(Integer id) {
        List<Integer> columnIds = columnMapper.selectByMoudleId(id);
        List<Moudle> moudles = queryMoudleListByParentId(id);
        JSONArray columns = new JSONArray();
        //List<Column> columns = new ArrayList<>();
        columnIds.forEach(columnId ->
                {
                    columns.add(columnService.queryById(columnId));
                }
        );
        for (Moudle moudle : moudles) {
            JSONArray columns1 = getColumns(moudle.getId());
            moudle.setColumnList(columns1);
            columns.add(JSONObject.parseObject(JSON.toJSONString(moudle)));
        }
        //  moudles.forEach( a -> {
        //List<Column> columns = getColumns(a.getId());
//            JSONArray columns1 = getColumns(a.getId());
//            a.setColumnList(columns1);
//            setChildrenList(a);
        //columns.add(JSONArray.parseArray(JSON.toJSONString(moudles)));
        // JSONArray columns1 = getColumns(a.getId());
        //  a.setColumnList(columns1);
        //  columns.add(JSONArray.parseArray(JSON.toJSONString(a)));
        //   });
        //moudle.setColumnList(JSONArray.parseArray(JSON.toJSONString(moudles)));
        return columns;
    }

    void setChildrenList(Moudle moudle) {
        List<Moudle> moudles = queryMoudleListByParentId(moudle.getId());
        moudles.forEach(a -> {
            //List<Column> columns = getColumns(a.getId());
            JSONArray columns = getColumns(a.getId());
            a.setColumnList(columns);
            setChildrenList(a);
        });
        moudle.setColumnList(JSONArray.parseArray(JSON.toJSONString(moudles)));
    }


    public boolean setNode(MoudleNode node, Integer moudleId, Integer columnType) {
        if (!isShow.get()) {
            isShow.set(false);
        }
        String currentUserId = TokenUserUtil.getCurrentUserId();
        List<Column> columns = queryColumnListByColumnId(moudleId);
        List<Moudle> moudles = queryMoudleListByParentId(moudleId);
        List<MoudleNode> list = new ArrayList<>();
        columns.forEach(a -> {
            MoudleNode childNode = new MoudleNode();
            childNode.setNodeName(a.getColumnName());
            childNode.setNodeEnName(a.getEnName());
            childNode.setId(a.getId());
            childNode.setColumnType(a.getColumnType());
            childNode.setType(2);
            childNode.setParentId(a.getMoudleId());
            //栏目树展示所有
            if (columnType == NumberConstant.NUMBER_1) {
                list.add(childNode);
                isShow.set(true);
            }
            //稿件树只展示column_typr为2、3、4、5的数据
            if ((a.getColumnType() == NumberConstant.NUMBER_2 || a.getColumnType() == NumberConstant.NUMBER_3 || a.getColumnType() == NumberConstant.NUMBER_4
                    || a.getColumnType() == NumberConstant.NUMBER_5 || a.getColumnType() == NumberConstant.NUMBER_6) && columnType == NumberConstant.NUMBER_2) {
                Moudle moudle = moudleMapper.selectById(a.getMoudleId());
                String moudleName = moudle.getMoudleName();
                Integer code = userMapper.judgeIsAdmin(currentUserId);
                if (code == null && !currentUserId.equals("superadmin")) {
                    User user = userMapper.selectById(currentUserId);
                    Center center = centerMapper.selectById(user.getCenterId());
                    Organization organization = organizationMapper.selectById(center.getOrganizationId());
                    if (organization.getOrganizationName().equals(moudleName) || organizationMapper.selectList(new LambdaQueryWrapper<Organization>().eq(Organization::getOrganizationName, moudleName)).size() == 0) {
                        list.add(childNode);
                        isShow.set(true);
                    }
                }
                if (code != null || currentUserId.equals("superadmin")) {
                    list.add(childNode);
                    isShow.set(true);
                }
            }
        });
        moudles.forEach(a -> {
            MoudleNode childNode = new MoudleNode();
            childNode.setNodeName(a.getMoudleName());
            childNode.setNodeEnName(a.getMoudleName());
            childNode.setId(a.getId());
            childNode.setType(1);
            childNode.setParentId(a.getParentId());
            childNode.setComponent(a.getComponent());
            childNode.setPath(a.getPath());
            childNode.setIsShow(a.getIsShow());
            childNode.setMoudleOrder(a.getMoudleOrder());
            boolean b = setNode(childNode, a.getId(), columnType);
            if (b) {
                isShow.set(true);
                if (childNode.getChildList().size() > 0) {
                    list.add(childNode);
                }
            } else if (columnType == NumberConstant.NUMBER_1) {
                isShow.set(false);
                list.add(childNode);
            } else {
                isShow.set(false);
            }
        });
        node.setChildList(list);
        return isShow.get();
    }

    public List<Column> queryColumnListByColumnId(Integer moudleId) {
        QueryWrapper<Column> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("moudle_id", moudleId);
        List<Column> columns = columnMapper.selectList(queryWrapper);
        return columns;
    }

    public List<Moudle> queryMoudleListByParentId(Integer moudleId) {
        QueryWrapper<Moudle> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", moudleId);
        List<Moudle> moudles = moudleMapper.selectList(queryWrapper);
        return moudles;
    }

    /**
     * 查询所有
     *
     * @return 查询结果
     */
    @Override
    public ResultVO queryList(Integer columnType, Integer websiteId) {
        String websiteIdByHeader = WebsiteUtil.getWebsiteId();
        if (websiteIdByHeader != null) {
            websiteId = Integer.parseInt(websiteIdByHeader);
        }
        List<MoudleNode> result;

        //jedis连接后一定会释放资源
        try {
            //jedis连接失败后不返回系统异常而是查数据库
            String redisStr = null;

            redisStr = JedisPoolFactory.select(REDIS_PREFIX + MOUDLEKEY + columnType);
            if (redisStr != null) {
                result = JSONArray.parseArray(redisStr, MoudleNode.class);
            } else {
                result = new ArrayList<>();
                QueryWrapper<Moudle> queryWrapper = new QueryWrapper<>();
                if (websiteId != null) {
                    queryWrapper.eq("website_id", websiteId);
                }
                queryWrapper.orderByAsc("level", "moudle_order");
                List<Moudle> moudles = moudleMapper.selectList(queryWrapper);
                List<Moudle> parentMoudles = moudles.stream().filter(a -> a.getLevel() == 1).collect(Collectors.toList());
                for (Moudle moudle : parentMoudles) {
                    MoudleNode node = new MoudleNode();
                    node.setNodeName(moudle.getMoudleName());
                    node.setNodeEnName(moudle.getEnName());
                    node.setId(moudle.getId());
                    node.setType(1);
                    node.setParentId(moudle.getParentId());
                    node.setComponent(moudle.getComponent());
                    node.setPath(moudle.getPath());
                    node.setIsShow(moudle.getIsShow());
                    node.setMoudleOrder(moudle.getMoudleOrder());
                    setNode(node, moudle.getId(), columnType);
                    //如果是稿件树并且有子集就添加
                    if (columnType != NUMBER_1 && node.getChildList().size() > 0) {
                        result.add(node);
                    }
                    //栏目树展示所有
                    if (columnType == NUMBER_1) {
                        result.add(node);
                    }
                }
                //JedisPoolFactory.setex(REDIS_PREFIX + MOUDLEKEY + columnType, DAY_SECOND, JSONArray.toJSONString(result));
            }
            return ResultVO.data(result);
        } catch (Exception e) {
            log.error("异常:{}", e.toString());
        }
        return ResultVO.fail(ResultCode.FAILURE);
    }

    /**
     * 新增数据
     *
     * @param moudle 实例对象
     * @return 实例对象
     */
    @Override
    public ResultVO insert(Moudle moudle) {
        if (moudle == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        QueryWrapper<Moudle> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", moudle.getParentId());
        Moudle moudleParent = moudleMapper.selectOne(queryWrapper);
        if (moudleParent != null) {
            moudle.setLevel(moudleParent.getLevel() + NUMBER_1);
        } else {
            moudle.setLevel(NUMBER_1);
            moudle.setParentId(NUMBER_0);
        }
        String websiteId = WebsiteUtil.getWebsiteId();
        if (websiteId != null) {
            moudle.setWebsiteId(Integer.parseInt(websiteId));
        }
        moudle.setIsDeleted(NUMBER_0);
        if (moudle.getMoudleOrder() == null) {
            moudle.setMoudleOrder("99");
        }
        if (StringUtils.isNotBlank(WebsiteUtil.getWebsiteId())) {
            moudle.setWebsiteId(Integer.parseInt(WebsiteUtil.getWebsiteId()));
        }
        moudleMapper.insert(moudle);
        // 清除缓存
        String redisKey = "STATION_GROUP_TREE_LIST" + WebsiteUtil.getWebsiteId();
        JedisPoolFactory.delete(redisKey);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    /**
     * 修改数据
     *
     * @param moudle 实例对象
     * @return 实例对象
     */
    @Override
    public ResultVO update(Moudle moudle) {
        if (moudle == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        QueryWrapper<Moudle> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", moudle.getParentId());
        Moudle moudleParent = moudleMapper.selectOne(queryWrapper);
        if (moudleParent != null) {
            moudle.setLevel(moudleParent.getLevel() + NUMBER_1);
        } else {
            moudle.setLevel(NUMBER_1);
            moudle.setParentId(NUMBER_0);
        }
        String websiteId = WebsiteUtil.getWebsiteId();
        if (websiteId != null) {
            moudle.setWebsiteId(Integer.parseInt(websiteId));
        }
//        moudle.setMoudleName(moudle.getNodeName());
//        moudle.setEnName(moudle.getNodeEnName());
        moudle.setIsDeleted(NUMBER_0);
        if (moudle.getMoudleOrder() == null) {
            moudle.setMoudleOrder("99");
        }
        moudleMapper.updateById(moudle);
        // 清除缓存
        String redisKey = "STATION_GROUP_TREE_LIST" + WebsiteUtil.getWebsiteId();
        JedisPoolFactory.delete(redisKey);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    /**
     * 修改数据
     *
     * @param moudle 实例对象
     * @return 实例对象
     */
    @Override
    public ResultVO updateName(Moudle moudle) {
        if (moudle == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        Moudle moudle1 = queryById(moudle.getId());
        if (moudle1 == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        if (moudle.getMoudleName() != null) {
            moudle1.setMoudleName(moudle.getMoudleName());
            moudle1.setEnName(moudle.getEnName());
        }
        moudleMapper.updateById(moudle);
        // 清除缓存
        String redisKey = "STATION_GROUP_TREE_LIST" + WebsiteUtil.getWebsiteId();
        JedisPoolFactory.delete(redisKey);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public ResultVO deleteById(Integer id) {
        if (id == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        if (queryById(id) == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        moudleMapper.deleteById(id);
        // 清除缓存
        String redisKey = "STATION_GROUP_TREE_LIST" + WebsiteUtil.getWebsiteId();
        JedisPoolFactory.delete(redisKey);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    @Override
    public ResultVO queryMoudleData(Integer id) {
        String redisValue = JedisPoolFactory.select(REDIS_PREFIX + MOUDLEDATAKEY + id);
        if (redisValue != null) {
            log.info("查询缓存{}", redisValue);
            return ResultVO.data(JSONObject.parse(redisValue));
        }
        QueryWrapper<Column> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("moudle_id", id);
        List<Column> columns = columnMapper.selectList(queryWrapper);
        List<Column> columnListType1 = new ArrayList<>();
        List<ColumnType2> columnListType2 = new ArrayList<>();
        List<ColumnType3> columnListType3 = new ArrayList<>();
        columns.parallelStream().forEach(a -> {
            if (a.getColumnType() == 1) {
                Column column = columnService.queryById(a.getId());
                columnListType1.add(column);
            }
            if (a.getColumnType() == 2) {
                ResultVO list = contentService.list(null, null, null, null, null, null, null, a.getId(), null, 1, 99);
                ColumnType2 columnType2 = new ColumnType2();
                BeanUtils.copyProperties(a, columnType2);
                columnType2.setData(list.getData());
                columnListType2.add(columnType2);
            }
            if (a.getColumnType() == 3) {
                ResultVO list = contentService.quoteList(null, null, null, null, null, null, a.getId(), 1, 99);
                ColumnType3 columnType3 = new ColumnType3();
                BeanUtils.copyProperties(a, columnType3);
                columnType3.setData(list.getData());
                columnListType3.add(columnType3);
            }
        });
        LinkedHashMap result = new LinkedHashMap();
        result.put("columnListType1", columnListType1);
        result.put("columnListType2", columnListType2);
        result.put("columnListType3", columnListType3);
        JedisPoolFactory.setex(REDIS_PREFIX + MOUDLEDATAKEY + id, 300, JSONObject.toJSONString(result));
        return ResultVO.data(result);
    }

    @Override
    public ResultVO getRouterList() {
        QueryWrapper<Moudle> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("level", NUMBER_1);
        queryWrapper.eq("is_show", NUMBER_1);
        queryWrapper.orderByAsc("moudle_order");
        List<Moudle> moudles = moudleMapper.selectList(queryWrapper);

        List<Router> routers = moudles.stream().map(item ->
        {
            QueryWrapper<Column> queryWrapper3 = new QueryWrapper<>();
            queryWrapper3.eq("moudle_id", item.getId());
            queryWrapper3.eq("is_router", NUMBER_3);
            Column column = columnMapper.selectOne(queryWrapper3);

            Router router = new Router();
            router.setRouterName(item.getMoudleName());
            router.setIdentify(item.getIdentify());
            router.setCid(item.getId());
            router.setPid(item.getParentId());
            if (StringUtils.isNotBlank(item.getEnName())) {
                router.setEnName(item.getEnName());
            }
            if (column != null) {
                router.setBannerId(column.getId());
            }
            return router;
        }).collect(Collectors.toList());
        moudles.forEach(moudle -> {
            QueryWrapper<Moudle> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("parent_id", moudle.getId());
            List<Moudle> moudleList = moudleMapper.selectList(queryWrapper1);
            QueryWrapper<Column> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2.eq("moudle_id", moudle.getId());
            queryWrapper2.eq("is_router", NUMBER_1);
            List<Column> columnList = columnMapper.selectList(queryWrapper2);
            JSONArray jsonArray = new JSONArray();
            List<Router> moudleNames = moudleList.stream().map(item -> {
                Router router = new Router();
                router.setRouterName(item.getMoudleName());
                router.setIdentify(item.getIdentify());
                router.setCid(item.getId());
                router.setPid(item.getParentId());
                if (StringUtils.isNotBlank(item.getEnName())) {
                    router.setEnName(item.getEnName());
                }
                return router;
            }).collect(Collectors.toList());
            List<Router> columnNames = columnList.stream().map(item -> {
                Router router = new Router();
                router.setRouterName(item.getColumnName());
                router.setIdentify(item.getIdentify());
                router.setCid(item.getId());
                router.setPid(item.getMoudleId());
                if (StringUtils.isNotBlank(item.getEnName())) {
                    router.setEnName(item.getEnName());
                }
                return router;
            }).collect(Collectors.toList());
            List<Router> routerNames = new ArrayList<>();
            routerNames.addAll(columnNames);
            routerNames.addAll(moudleNames);
            jsonArray.add(routerNames);
            moudle.setColumnList(jsonArray.get(0));
        });
        for (int i = 0; i < routers.size(); i++) {
            CopyBeanUtils.copyProperties(moudles.get(i), routers.get(i));
        }
        return ResultVO.data(routers);
    }

    @Override
    public ResultVO getTreeList() {
        String websiteId = WebsiteUtil.getWebsiteId();
        String redisKey = "STATION_GROUP_TREE_LIST" + websiteId;
        String dataList = JedisPoolFactory.select(redisKey);
        if (StringUtils.isNotEmpty(dataList)) {
            List<MoudleVo> moudleVoList = JSONArray.parseArray(dataList, MoudleVo.class);
            return ResultVO.data(moudleVoList);
        }
        QueryWrapper<Moudle> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(websiteId)) {
            queryWrapper.eq("website_id", websiteId);
        }
        List<Moudle> modules = moudleMapper.selectList(queryWrapper).stream().filter(s -> s.getParentId() != null).collect(Collectors.toList());
        List<MoudleVo> moudleTemp = new ArrayList<>();
        for (int i = 0; i < modules.size(); i++) {
            moudleTemp.add(new MoudleVo());
            CopyBeanUtils.copyProperties(modules.get(i), moudleTemp.get(i));
        }
        ArrayList<MoudleVo> moduleList = new ArrayList<>();
        for (MoudleVo mod : moudleTemp) {
            if (mod.getParentId() != null && mod.getParentId() == 0) {
                moduleList.add(mod);
            }
        }
        List<MoudleVo> moudleVos = setMoudles(moudleTemp, moduleList);
        JedisPoolFactory.setex(redisKey, 60 * 2, JSONArray.toJSONString(moudleVos, SerializerFeature.WriteDateUseDateFormat));
        return ResultVO.data(moudleVos);
    }

    @Override
    public ResultVO recommendMoudle(String columnName) {
        JSONArray jsonArrayMoudle = new JSONArray();
        JSONObject jsonObjectMoudle1 = new JSONObject();
        jsonObjectMoudle1.put("id", "1");
        jsonObjectMoudle1.put("name", "首页");
        Moudle moudle = moudleMapper.selectOne(new LambdaQueryWrapper<Moudle>().eq(Moudle::getMoudleName, columnName).eq(Moudle::getWebsiteId, WebsiteUtil.getWebsiteId()));
        if (moudle == null) return ResultVO.fail("栏目名称错误");
        JSONObject jsonObjectMoudle2 = new JSONObject();
        Moudle pMoudle = moudleMapper.selectOne(new LambdaQueryWrapper<Moudle>().eq(Moudle::getId, moudle.getParentId()));
        if (pMoudle == null) {
            jsonObjectMoudle2.put("id", moudle.getId());
            jsonObjectMoudle2.put("name", moudle.getMoudleName());
        } else {
            jsonObjectMoudle2.put("id", pMoudle.getId());
            jsonObjectMoudle2.put("name", pMoudle.getMoudleName());
        }
        List<Column> columnList = columnMapper.selectList(new LambdaQueryWrapper<Column>().eq(Column::getColumnType, 3)
                .in(Column::getMoudleId, moudleMapper.queryMoudleByWebsiteId(WebsiteUtil.getWebsiteId())));
        JSONArray jsonArray = new JSONArray();
        JSONArray jsonArray2 = new JSONArray();
        columnList.forEach(column -> {
            JSONObject jsonObjectMoudle = new JSONObject();
            jsonObjectMoudle.put("id", column.getId());
            jsonObjectMoudle.put("name", column.getColumnName());
            if (column.getColumnName().equals(moudle.getMoudleName())) {
                jsonArray.add(jsonObjectMoudle);
                jsonObjectMoudle2.put("children", jsonArray);
            } else {
                jsonArray2.add(jsonObjectMoudle);
                jsonObjectMoudle1.put("children", jsonArray2);
            }
        });
        jsonArrayMoudle.add(jsonObjectMoudle1);
        jsonArrayMoudle.add(jsonObjectMoudle2);
        return ResultVO.data(jsonArrayMoudle);
    }

    private List<MoudleVo> setMoudles(List<MoudleVo> moudleTemp, List<MoudleVo> moduleList) {
        List<MoudleVo> moudleVos = moduleList.stream().sorted(Comparator.comparing(MoudleVo::getMoudleOrder)).collect(Collectors.toList());
        moudleVos.forEach(moudle -> {
            ArrayList<MoudleVo> childrenList = new ArrayList<>();
            moudleTemp.forEach(s -> {
                if (s.getParentId().equals(moudle.getId())) {
                    childrenList.add(s);
                }
            });
            List<MoudleVo> sorted = childrenList.stream().sorted(Comparator.comparing(MoudleVo::getMoudleOrder)).collect(Collectors.toList());
            moudle.setChildrenList(sorted);
            setMoudles(moudleTemp, moudle.getChildrenList());
        });
        return moudleVos;
    }
}
